package com.net.xpay.web.controller.open;


import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.net.xpay.web.dto.openapi.OpenApiChargeRecordNotifyDto;
import com.net.common.util.MoneyUtil;
import com.net.common.util.SerializationUtil;
import com.net.xpay.alipay.common.CommonAlipayClient;
import com.net.xpay.alipay.common.model.AlipayTradeNotifyModel;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.notify.ChargeRecordNotifyRecord;
import com.net.xpay.common.domain.openapi.OpenApp;
import com.net.xpay.common.enums.notify.NotifyStatus;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.notify.ChargeRecordNotifyRecordManager;
import com.net.xpay.common.manager.openapi.OpenAppManager;
import com.net.xpay.core.domain.ChargeRecord;
import com.net.xpay.core.enums.PayStatus;
import com.net.xpay.core.service.ChargeRecordNotifyRecordService;
import com.net.xpay.core.service.ChargeService;
import com.net.shard.ShardUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;


@Api(tags = "支付宝充值订单支付结果通知")
@Slf4j
@RestController
@RequestMapping("/open")
public class AlipayPayNotifyController {

    @Autowired
    private CommonAlipayClient commonAlipayClient;


    @Autowired
    private ChargeService chargeService;

    @Autowired
    private ChargeRecordNotifyRecordService chargeRecordNotifyRecordService;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private OpenAppManager openAppManager;

    @Autowired
    private ChargeRecordNotifyRecordManager chargeRecordNotifyRecordManager;

    @ApiOperation("支付宝订单支付结果通知")
    @PostMapping("/common-pay-result-notify")
    public String onAlipayResultNotify(HttpServletRequest request) {
        log.info("onAlipayResultNotify before params={}", JSONObject.toJSONString(request.getParameterMap()));

        Map<String, String> map = new HashMap<>();

        request.getParameterMap().forEach((k, v)-> {
            if (!Strings.isNullOrEmpty(v[0])) {
                map.put(k, v[0]);
            }
        });


        log.info("onAlipayResultNotify after params={}", JSONObject.toJSONString(map));
        try {
            //判断sign是否一致
            boolean validSign = commonAlipayClient.checkSignV1(map);
            if (validSign) {
                if ("trade_status_sync".equals(map.get("notify_type"))) {
                    AlipayTradeNotifyModel notifyModel = JSONObject.parseObject(JSONObject.toJSONString(map), AlipayTradeNotifyModel.class);
                    String userId = notifyModel.getOutTradeNo().split("_")[0];
                    UserShard shard = userShardManager.getById(Long.valueOf(userId));
                    try {
                        ShardUtil.setShardContext(shard.getShardId());
                        ChargeRecord chargeRecord = chargeService.onCommonPayNotify(notifyModel);
                        if (chargeRecord != null) {
                            processChargeRecordNotify(chargeRecord);
                        }

                    } finally {
                        ShardUtil.cleanShardContext();
                    }
                } else {
                    log.warn("onAlipayResultNotify unknown notify type={}", map.get("notify_type"));
                }
                return "success";
            }
            return "error";
        } catch (Exception e) {
            log.error("onAlipayResultNotify error|params={}", JSONObject.toJSONString(map), e);
            return "error";
        }
    }

    private void processChargeRecordNotify(ChargeRecord chargeRecord) {
        if (Strings.isNullOrEmpty(chargeRecord.getNotifyUrl())){
            return;
        }
        OpenApp openApp = openAppManager.getByUserId(chargeRecord.getUserId());
        ChargeRecordNotifyRecord chargeRecordNotifyRecord = new ChargeRecordNotifyRecord();
        chargeRecordNotifyRecord.setUserId(chargeRecord.getUserId());
        chargeRecordNotifyRecord.setAppId(openApp.getId());
        chargeRecordNotifyRecord.setImportBizNo(chargeRecord.getImportBizNo());
        chargeRecordNotifyRecord.setChargeRecordId(chargeRecord.getId());
        chargeRecordNotifyRecord.setStatus(NotifyStatus.WAIT);
        chargeRecordNotifyRecord.setNotifyCount(0);
        chargeRecordNotifyRecord.setNextNotifyTime(LocalDateTime.now());
        chargeRecordNotifyRecord.setNotifyUrl(chargeRecord.getNotifyUrl());

        OpenApiChargeRecordNotifyDto dto = new OpenApiChargeRecordNotifyDto();
        dto.setAmount(MoneyUtil.convertCentToString(chargeRecord.getAmount(), 2));
        dto.setImportBizNo(chargeRecord.getImportBizNo());
        dto.setTradeNo(chargeRecord.getDetailId());
        dto.setPayStatus(chargeRecord.getPayStatus());
        dto.setChargeRecordId(chargeRecord.getId().toString());
        if (chargeRecord.getPayStatus() == PayStatus.PAYED) {
            dto.setPayTime(chargeRecord.getEndTime());
        }

        dto.setCreateTime(chargeRecord.getCreateTime());

        chargeRecordNotifyRecord.setNotifyContent(SerializationUtil.obj2String(dto));

        chargeRecordNotifyRecordManager.save(chargeRecordNotifyRecord);
        try {
            chargeRecordNotifyRecordService.notifyChargeRecordNotifyRecord(chargeRecordNotifyRecord);
        }catch (Exception e){
            log.info("processChargeRecordNotify error|params={}", SerializationUtil.obj2String(chargeRecord) );
        }
    }
}
